1.实体类解析与表的创建

image-20181222214114017

image-20181222214145357


image-20181223070542815


image-20181223072622146


image-20181223082052754


image-20181223082844242


image-20181223090734422


image-20181223093042614

$商品类别$:

1:商品类别的id

2:店铺id

3:商品类别的名称

4:商品类别的权重

5:商品创建时间


$详情图片:$

image-20181223093754350

1:详情图片的id

2.图片的地址

3.图片显示的权重 大靠前显示

4.创建时间

5.属于那个商品的详情图片(多对一)的关系


image-20181223094705247


image-20181223101020928


image-20181223101120198


image-20181223101240234


image-20181223101255059


image-20181223101804614


2 SprintBoot环境搭载

2.1 maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.imooc.demo</groupId>
<artifactId>myo2o</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>myo2o Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>4.3.7.RELEASE</spring.version>
</properties>


<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

<!-- 1.日志 -->
<!-- 实现slf4j接口并整合 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.1</version>
</dependency>

<!-- 2.数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>

<!-- DAO: MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>

<!-- 3.Servlet web -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>

<!-- 4.Spring -->
<!-- 1)Spring核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 2)Spring DAO层 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 3)Spring web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 4)Spring test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- redis客户端:Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.0.12</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.0.12</version>
</dependency>

<!-- Map工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<!-- wechat相关 -->
<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
<!-- 二维码相关 -->
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>


</dependencies>
<build>
<finalName>myo2o</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</projec

###2.2 环境搭建SSM

jdbc.properties

1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/o2odb?useUnicode=true&characterEncoding=utf8
jdbc.username=WnplV/ietfQ=
jdbc.password=TdixoQRe6Y0=

logback.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 <?xml version="1.0" encoding="utf-8" standalone="no"?>
<configuration debug="false">
<appender name="INFO-FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${catalina.base}/webapps/myo2o/logs/info/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${catalina.base}/webapps/myo2o/logs/info/info.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1024MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{55} -
%msg%n
</pattern>
</layout>
</appender>
<appender name="ACCESS-FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>
${catalina.base}/webapps/myo2o/logs/access/access.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${catalina.base}/webapps/myo2o/logs/access/access.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1024MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{55} -
%msg%n
</pattern>
</layout>
</appender>
<logger name="com.imooc.myo2o" level="DEBUG" additivity="false">
<appender-ref ref="ACCESS-FILE" />
</logger>
<root level="INFO">
<appender-ref ref="INFO-FILE" />
</root>
</configuration>

mybatis-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置全局属性 -->
<settings>
<!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
<setting name="useGeneratedKeys" value="true" />

<!-- 使用列别名替换列名 默认:true -->
<setting name="useColumnLabel" value="true" />

<!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
</configuration>

redis.properties

1
2
3
4
5
6
7
redis.hostname=127.0.0.1
redis.port=6379
redis.database=0
redis.pool.maxActive=600
redis.pool.maxIdle=300
redis.pool.maxWait=3000
redis.pool.testOnBorrow=true

weixin.properties

1
2
weixinappid=PTv/7qETW0kO5N0WT223IlBEOUuK0+SO
weixinappsecret=jOjEubTD3dTzTbNzX+vREKnTJvvKZRud6c3712kCaGgfJAfVsP+M2w==

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1" metadata-complete="true">
<!-- 如果是用mvn命令生成的xml,需要修改servlet版本为3.1 -->
<servlet>
<!-- 生成图片的Servlet -->
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>

<!-- 是否有边框 -->
<init-param>
<param-name>kaptcha.border</param-name>
<param-value>no</param-value>
</init-param>
<!-- 字体颜色 -->
<init-param>
<param-name>kaptcha.textproducer.font.color</param-name>
<param-value>red</param-value>
</init-param>
<!-- 图片宽度 -->
<init-param>
<param-name>kaptcha.image.width</param-name>
<param-value>135</param-value>
</init-param>
<!-- 使用哪些字符生成验证码 -->
<init-param>
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>ACDEFHKPRSTWX345679</param-value>
</init-param>
<!-- 图片高度 -->
<init-param>
<param-name>kaptcha.image.height</param-name>
<param-value>50</param-value>
</init-param>
<!-- 字体大小 -->
<init-param>
<param-name>kaptcha.textproducer.font.size</param-name>
<param-value>43</param-value>
</init-param>
<!-- 干扰线的颜色 -->
<init-param>
<param-name>kaptcha.noise.color</param-name>
<param-value>black</param-value>
</init-param>
<!-- 字符个数 -->
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<!-- 使用哪些字体 -->
<init-param>
<param-name>kaptcha.textproducer.font.names</param-name>
<param-value>Arial</param-value>
</init-param>
</servlet>
<!-- 映射的url -->
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/Kaptcha</url-pattern>
</servlet-mapping>
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>seckill-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springMVC需要加载的配置文件 spring-dao.xml,spring-service.xml,spring-web.xml
Mybatis - > spring -> springmvc -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>seckill-dispatcher</servlet-name>
<!-- 默认匹配所有的请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

Spring

spring-dao.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置整合mybatis过程 -->
<!-- 1.配置数据库相关参数properties的属性:${url} -->
<bean class="com.imooc.myo2o.util.EncryptPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:redis.properties</value>
</list>
</property>
<property name="fileEncoding" value="UTF-8" />
</bean>
<!-- 2.数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接池属性 -->
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />

<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30" />
<property name="minPoolSize" value="10" />
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false" />
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000" />
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2" />
</bean>

<!-- 3.配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 扫描entity包 使用别名 -->
<property name="typeAliasesPackage" value="com.imooc.myo2o.entity" />
<!-- 扫描sql配置文件:mapper需要的xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>

<!-- 4.配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!-- 给出需要扫描Dao接口包 -->
<property name="basePackage" value="com.imooc.myo2o.dao" />
</bean>
</beans>

spring-redis.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxActive}" />
<property name="maxIdle" value="${redis.pool.maxIdle}" />
<property name="maxWaitMillis" value="${redis.pool.maxWait}" />
<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
</bean>

<bean id="jedisWritePool" class="com.imooc.myo2o.cache.JedisPoolWriper"
depends-on="jedisPoolConfig">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${redis.hostname}" />
<constructor-arg index="2" value="${redis.port}" type="int" />
</bean>
<bean id="jedisKeys" class="com.imooc.myo2o.cache.JedisUtil$Keys"
scope="singleton">
<constructor-arg ref="jedisUtil"></constructor-arg>
</bean>
<bean id="jedisStrings" class="com.imooc.myo2o.cache.JedisUtil$Strings"
scope="singleton">
<constructor-arg ref="jedisUtil"></constructor-arg>
</bean>
<bean id="jedisLists" class="com.imooc.myo2o.cache.JedisUtil$Lists"
scope="singleton">
<constructor-arg ref="jedisUtil"></constructor-arg>
</bean>
<bean id="jedisSets" class="com.imooc.myo2o.cache.JedisUtil$Sets"
scope="singleton">
<constructor-arg ref="jedisUtil"></constructor-arg>
</bean>
<bean id="jedisHash" class="com.imooc.myo2o.cache.JedisUtil$Hash"
scope="singleton">
<constructor-arg ref="jedisUtil"></constructor-arg>
</bean>
<bean id="jedisUtil" class="com.imooc.myo2o.cache.JedisUtil"
scope="singleton">
<property name="jedisPool">
<ref bean="jedisWritePool" />
</property>
</bean>
</beans>

spring-service.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描service包下所有使用注解的类型 -->
<context:component-scan base-package="com.imooc.myo2o.service" />

<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 配置基于注解的声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

spring -web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解模式 -->
<!-- 简化配置: (1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter
(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持 -->
<mvc:annotation-driven />

<!-- 2.静态资源默认servlet配置 (1)加入对静态资源的处理:js,gif,png (2)允许使用"/"做整体映射 -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:default-servlet-handler />

<!-- 3.定义视图解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/html/"></property>
<property name="suffix" value=".html"></property>
</bean>
<!-- 文件上传解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<property name="maxUploadSize" value="10485760000"></property><!-- 最大上传文件大小 -->
<property name="maxInMemorySize" value="10960"></property>
</bean>
<!-- 在spring-mvc.xml文件中加入这段配置后,spring返回给页面的都是utf-8编码了 -->
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<!-- 4.扫描web相关的bean -->
<context:component-scan base-package="com.imooc.myo2o.web" />
<!-- 5.权限拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/shop/**" />
<mvc:exclude-mapping path="/shop/ownerlogin" />
<mvc:exclude-mapping path="/shop/ownerlogincheck" />
<mvc:exclude-mapping path="/shop/logout" />
<mvc:exclude-mapping path="/shop/register" />
<bean id="ShopInterceptor" class="com.imooc.myo2o.interceptor.shop.ShopLoginInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/shop/**" />
<mvc:exclude-mapping path="/shop/ownerlogin" />
<mvc:exclude-mapping path="/shop/ownerlogincheck" />
<mvc:exclude-mapping path="/shop/register" />
<!-- shoplist page -->
<mvc:exclude-mapping path="/shop/shoplist" />
<mvc:exclude-mapping path="/shop/logout" />
<mvc:exclude-mapping path="/shop/list" />
<!-- changepsw page -->
<mvc:exclude-mapping path="/shop/changepsw" />
<mvc:exclude-mapping path="/shop/changelocalpwd" />
<!-- ownerbind page -->
<mvc:exclude-mapping path="/shop/ownerbind" />
<mvc:exclude-mapping path="/shop/bindlocalauth" />
<!-- shopmanage page -->
<mvc:exclude-mapping path="/shop/shopmanage" />
<!-- shopedit page -->
<mvc:exclude-mapping path="/shop/shopedit" />
<mvc:exclude-mapping path="/shop/getshopbyid" />
<mvc:exclude-mapping path="/shop/getshopinitinfo" />
<mvc:exclude-mapping path="/shop/registershop" />
<bean id="ShopPermissionInterceptor"
class="com.imooc.myo2o.interceptor.shop.ShopPermissionInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/superadmin/**" />
<mvc:exclude-mapping path="/superadmin/login" />
<mvc:exclude-mapping path="/superadmin/logincheck" />
<mvc:exclude-mapping path="/superadmin/main" />
<mvc:exclude-mapping path="/superadmin/top" />
<bean id="SuperAdminInterceptor"
class="com.imooc.myo2o.interceptor.superadmin.SuperAdminLoginInterceptor" />
</mvc:interceptor>

</mvc:interceptors>
</beans>

3 SpringBoot整合SSM项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# mybatis
#1 domain POJO entity 层 就是实体类
mybatis.type-aliases-package=com.imooc.o2o.o2o.domain
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=3000
mybatis.mapperLocations=classpath:mapperxml/*.xml
# druid
spring.datasource.url=jdbc:mysql://localhost:3306/o2o?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=YHP836143
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters=stat
spring.datasource.maxActive=2
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=select 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements=20
#thymeleaf start
spring.thymeleaf.cache=false
spring.thymeleaf.servlet.content-type=text/html
#spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML5
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
#Redis的相关配置

#spring.redis.database=1
#spring.redis.host=127.0.0.1
#spring.redis.port=6379
#spring.redis.password=
#spring.redis.lettuce.pool.max-active=8
#spring.redis.lettuce.pool.max-wait=-1
#spring.redis.lettuce.pool.max-idle=8
#spring.redis.lettuce.pool.min-idle=0


#dubbo的配置
#dubbo.application.name=taotaomall
#dubbo.registry.address=94.191.24.33:2181
#dubbo.registry.protocol=zookeeper
#dubbo.protocol.name=dubbo
#dubbo.monitor.protocol=registry
#dubbo.protocol.port=2181

4 项目1.0开发 店铺注册功能模块

image-20190302190948377

4.1新增加店铺跟新店铺开发

  • dao层

    1
    2
      //1 开发功能1 新增店铺
    int insert(TbShop record);
  • xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<insert id="insert" keyColumn="shop_id" keyProperty="shopId" parameterType="com.imooc.o2o.o2o.domain.TbShop" useGeneratedKeys="true">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into tb_shop (owner_id, area_id, shop_category_id,
parent_category_id, shop_name, shop_desc,
shop_addr, phone, shop_img,
longitude, latitude, priority,
create_time, last_edit_time, enable_status,
advice)
values (#{ownerId,jdbcType=INTEGER}, #{areaId,jdbcType=INTEGER}, #{shopCategoryId,jdbcType=INTEGER},
#{parentCategoryId,jdbcType=INTEGER}, #{shopName,jdbcType=VARCHAR}, #{shopDesc,jdbcType=VARCHAR},
#{shopAddr,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{shopImg,jdbcType=VARCHAR},
#{longitude,jdbcType=DOUBLE}, #{latitude,jdbcType=DOUBLE}, #{priority,jdbcType=INTEGER},
#{createTime,jdbcType=TIMESTAMP}, #{lastEditTime,jdbcType=TIMESTAMP}, #{enableStatus,jdbcType=INTEGER},
#{advice,jdbcType=VARCHAR})
</insert>

  • 1
    int updateByPrimaryKeySelective(TbShop record);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * update tb_shop
    * <set>
    * <if test="ownerId != null">
    * owner_id = #{ownerId,jdbcType=INTEGER},
    * area_id = #{areaId,jdbcType=INTEGER},
    * </if>
    * <if test="shopCategoryId != null">
    * </set>
    * where shop_id = #{shopId,jdbcType=INTEGER}
    */

    4.2 Thumbnailator图片处理和封装Util

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
---
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>

https://github.com/coobird/thumbnailator/wiki/Examples

1
2
3
Thumbnails.of(new File("original.jpg"))
.size(160, 160)
.toFile(new File("thumbnail.jpg"));
1
2
3
4
5
6
Thumbnails.of(new File("original.jpg"))
.size(160, 160)
.rotate(90)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("watermark.png")), 0.5f)
.outputQuality(0.8)
.toFile(new File("image-with-watermark.jpg"));

5 thumbnails图像处理库的使用


  • imageUtils
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.imooc.o2o.o2o.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

//https://www.jianshu.com/p/04d04afc34fd简书
public class ImageUtil {
public static String generateThumbnail(CommonsMultipartFile thumbnail, String targetAddr) {
String realFileName = FileUtil.getRandomFileName();
String extension = getFileExtension(thumbnail);
makeDirPath(targetAddr);
String relativeAddr = targetAddr + realFileName + extension;
File dest = new File(FileUtil.getImgBasePath() + relativeAddr);
try {
Thumbnails.of(thumbnail.getInputStream()).size(200, 200).outputQuality(0.25f).toFile(dest);
} catch (IOException e) {
throw new RuntimeException("创建缩略图失败:" + e.toString());
}
return relativeAddr;
}


public static String generateNormalImg(CommonsMultipartFile thumbnail, String targetAddr) {
String realFileName = FileUtil.getRandomFileName();
String extension = getFileExtension(thumbnail);
makeDirPath(targetAddr);
String relativeAddr = targetAddr + realFileName + extension;
File dest = new File(FileUtil.getImgBasePath() + relativeAddr);
try {
Thumbnails.of(thumbnail.getInputStream()).size(337, 640).outputQuality(0.5f).toFile(dest);
} catch (IOException e) {
throw new RuntimeException("创建缩略图失败:" + e.toString());
}
return relativeAddr;
}


public static List<String> generateNormalImgs(List<CommonsMultipartFile> imgs, String targetAddr) {
int count = 0;
List<String> relativeAddrList = new ArrayList<String>();
if (imgs != null && imgs.size() > 0) {
makeDirPath(targetAddr);
for (CommonsMultipartFile img : imgs) {
String realFileName = FileUtil.getRandomFileName();
String extension = getFileExtension(img);
String relativeAddr = targetAddr + realFileName + count + extension;
File dest = new File(FileUtil.getImgBasePath() + relativeAddr);
count++;
try {
Thumbnails.of(img.getInputStream()).size(600, 300).outputQuality(0.5f).toFile(dest);
} catch (IOException e) {
throw new RuntimeException("创建图片失败:" + e.toString());
}
relativeAddrList.add(relativeAddr);
}
}
return relativeAddrList;
}


//* 目标路径文件夹不存在就创建
private static void makeDirPath(String targetAddr) {
String realFileParentPath = FileUtil.getImgBasePath() + targetAddr;
File dirPath = new File(realFileParentPath);
if (!dirPath.exists()) {
dirPath.mkdirs();
}
}

//* 获取输入文件流的扩展名
private static String getFileExtension(CommonsMultipartFile cFile) {
String originalFileName = cFile.getOriginalFilename();
return originalFileName.substring(originalFileName.lastIndexOf("."));
}
//}

}
  • FileUtil
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.imooc.o2o.o2o.util;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class FileUtil {
private static String seperator = System.getProperty("file.separator");
private static final SimpleDateFormat sDateFormat = new SimpleDateFormat(
"yyyyMMddHHmmss"); // 时间格式化的格式
private static final Random r = new Random();

public static String getImgBasePath() {
String os = System.getProperty("os.name");
String basePath = "";
if (os.toLowerCase().startsWith("win")) {
basePath = "D:/projectdev/image/";
} else {
basePath = "/home/xiangzepro/";
}
basePath = basePath.replace("/", seperator);
return basePath;
}

public static String getHeadLineImagePath() {
String headLineImagePath = "/upload/images/item/headtitle/";
headLineImagePath = headLineImagePath.replace("/", seperator);
return headLineImagePath;
}

public static String getShopCategoryImagePath() {
String shopCategoryImagePath = "/upload/images/item/shopcategory/";
shopCategoryImagePath = shopCategoryImagePath.replace("/", seperator);
return shopCategoryImagePath;
}

//
public static String getPersonInfoImagePath() {
String personInfoImagePath = "/upload/images/item/personinfo/";
personInfoImagePath = personInfoImagePath.replace("/", seperator);
return personInfoImagePath;
}

public static String getShopImagePath(long shopId) {
StringBuilder shopImagePathBuilder = new StringBuilder();
shopImagePathBuilder.append("/upload/images/item/shop/");
shopImagePathBuilder.append(shopId);
shopImagePathBuilder.append("/");
String shopImagePath = shopImagePathBuilder.toString().replace("/",
seperator);
return shopImagePath;
}

//
public static String getRandomFileName() {
// 生成随机文件名:当前年月日时分秒+五位随机数(为了在实际项目中防止文件同名而进行的处理)
int rannum = (int) (r.nextDouble() * (99999 - 10000 + 1)) + 10000; // 获取随机数
String nowTimeStr = sDateFormat.format(new Date()); // 当前时间
return nowTimeStr + rannum;
}

//
public static void deleteFile(String storePath) {
File file = new File(getImgBasePath() + storePath);
if (file.exists()) {
if (file.isDirectory()) {
File files[] = file.listFiles();
for (int i = 0; i < files.length; i++) {
files[i].delete();
}
}
file.delete();
}
}
}

https://www.jianshu.com/p/04d04afc34fd.

6 Dto的开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class ShopExcution {
//结果状态
private int state;
//状态标识
private String stateInfo;
//店铺的数量
private int count;
//操作的shop(增删改查店铺的时候用到)
private TbShop tbShop;
//shop列表(查询店铺列表的时候使用)
private List<TbShop> shopList;

public ShopExcution() {
}

//构造方法 传入两个参数
//店铺操作失败的时候 用的构造方法
public ShopExcution(ShopStateEnum stateEnum) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
}

//店铺成功的时候所用的构造方法 成功才能返回店铺信息
public ShopExcution(ShopStateEnum stateEnum, TbShop tbShop) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
this.tbShop = tbShop;
}

//店铺成功的时候所用的构造方法 成功才能返回店铺信息tbListShop
public ShopExcution(ShopStateEnum stateEnum, List<TbShop> tbShopList) {
this.state = stateEnum.getState();
this.stateInfo = stateEnum.getStateInfo();
this.shopList = tbShopList;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public enum ShopStateEnum {

//枚举里面的参数 就是定义的成员变量的值
CHECK(0, "审核中"),
OFFLINE(-1, "非法商铺"),
SUCCESS(1, "操作成功"),
PASS(2, "通过认证"),
INNER_ERROR(-1001, "操作失败"),
NULL_SHOPID(-1002, "ShopId为空"),
NULL_SHOP_INFO(-1003, "传入了空的信息");

private int state;
private String stateInfo;

private ShopStateEnum(int state, String stateInfo) {
this.state = state;
this.stateInfo = stateInfo;
}

public int getState() {
return state;
}

public String getStateInfo() {
return stateInfo;
}

//依据传入的state返回相应的enum值
public static ShopStateEnum stateOf(int index) {
//这个方法会返回包括所有枚举变量的数组。在该例中,返回的就是包含了七个星期的Weekday[]。可以方便的用来做循环。
//index =state state的值已经定义好了

for (ShopStateEnum stateEnum : ShopStateEnum.values()) {
if (stateEnum.getState() == index)
return stateEnum;
}
return null;
}

7 Service层的开发—添加店铺 和店铺图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public class ShopServiceImpl implements ShopService {
private TbShopMapper tbShopMapper;

@Override
@Transactional
public ShopExcution addShop(TbShop tbShop, CommonsMultipartFile ShopImg) {
//空值判断
if (tbShop == null) {
//调用了ShopStateExcution失败的方法 返回枚举里面的数据
//ShopStateEnum.NULL_SHOP_INFO=(-1003, "传入了空的信息")
return new ShopExcution(ShopStateEnum.NULL_SHOP_INFO);
}
//给店铺信息赋初始值
tbShop.setEnableStatus(0);
tbShop.setCreateTime(new Date());
tbShop.setLastEditTime(new Date());
/*
tbShopMapper :int insert(TbShop record);属性
insert into tb_shop
(owner_id, area_id, shop_category_id,...)values=#{...}
*/
//添加店铺信息
int effectedNum = tbShopMapper.insert(tbShop);
if (effectedNum <= 0) {
throw new RuntimeException("店铺创建失败");
}
//店铺添加成功
else {
//存储图片
if (ShopImg != null) {
addShopImg(tbShop, ShopImg);//根据tbShop里面的id存储图片 更新图片
//更新店铺的图片地址 只更新一个字段吗????
effectedNum = tbShopMapper.updateByPrimaryKeySelective(tbShop);
if (effectedNum <= 0) {
throw new RuntimeException("店铺更新图片地址失败");
}
}
}
return new ShopExcution(ShopStateEnum.CHECK, tbShop);
}
//添加店铺图片 ⭐️⭐️⭐️⭐️⭐️⭐️
private void addShopImg(TbShop tbShop, CommonsMultipartFile shopImg) {
//1 获取Shop图片目录的相对值路径
/**
* public static String getShopImagePath(long shopId) {
* StringBuilder shopImagePathBuilder = new StringBuilder();
* shopImagePathBuilder.append("/upload/images/item/shop/");
* shopImagePathBuilder.append(shopId);
* shopImagePathBuilder.append("/");
* String shopImagePath = shopImagePathBuilder.toString().replace("/",
* seperator);
* return shopImagePath;
* }
*/
String shopImagePath = FileUtil.getShopImagePath(tbShop.getShopId());
//2 存储图片返回相对子路径 imageUtil
/**
* public static String generateThumbnail(CommonsMultipartFile thumbnail, String targetAddr) {
* String realFileName = FileUtil.getRandomFileName();
* String extension = getFileExtension(thumbnail);
* makeDirPath(targetAddr);
* String relativeAddr = targetAddr + realFileName + extension;
* File dest = new File(FileUtil.getImgBasePath() + relativeAddr);
* try {
* Thumbnails.of(thumbnail.getInputStream()).size(200, 200).outputQuality(0.25f).toFile(dest);
* } catch (IOException e) {
* throw new RuntimeException("创建缩略图失败:" + e.toString());
* }
* return relativeAddr;
* }* 对图片进行压缩并加水印
* //https://www.jianshu.com/p/04d04afc34fd简书
*/
String shopImgAddr = ImageUtil.generateThumbnail(shopImg, shopImagePath);
tbShop.setShopImg(shopImgAddr);
}
}

1
2
3
4
5
public class ShopOperationException extends RuntimeException {
public ShopOperationException(String msg) {
super(msg);
}
}

8 店铺注册功能Controller层的实现 ⭐️ ⭐️ ⭐️

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//实现店铺管理相关的逻辑店铺注册功能Controller层的实现
//先从前端拿到字段 然后注册到数据库里面
@Controller
@RequestMapping("/shopadmin")
public class ShopManagementController {
@Autowired
private ShopServiceImpl shopService;

@RequestMapping("/registershop")
@ResponseBody
public Map<String, Object> registerShop(HttpServletRequest request) throws IOException {
Map<String, Object> modelMap = new HashMap<>();
//1 接受并转化相应的参数 包括店铺信息以及图片信息 解析request的参数
//就是 request.getParameter(name);
String shopStr = HttpServletRequestUtil.getString(request, "shopStr");
ObjectMapper mapper = new ObjectMapper();
TbShop tbShop = null;
try {
//将字符串转为实体类
tbShop = mapper.readValue(shopStr, TbShop.class);
} catch (Exception e) {
modelMap.put("scuuess", false);
modelMap.put("errMsg", e.getMessage());
return modelMap;
}
//2 接受图片
CommonsMultipartFile shopImg = null;
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
if (commonsMultipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "图片上传不能为空");
return modelMap;
}
//2 注册店铺
if (tbShop != null && shopImg != null) {
TbPersonInfo tbPersonInfo = new TbPersonInfo();
tbPersonInfo.setUserId(1);
tbShop.setOwner(tbPersonInfo);
//添加shopService
ShopExcution shopExcution = shopService.addShop(tbShop, shopImg);
if (shopExcution.getState() == ShopStateEnum.CHECK.getState()) {
modelMap.put("success", true);
return modelMap;
} else {
modelMap.put("success", false);
modelMap.put("errMsg", shopExcution.getState());
return modelMap;
}
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "图片上传不能为空");
return modelMap;
}
}

1 HttpServletRequestUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import javax.servlet.http.HttpServletRequest;
public class HttpServletRequestUtil {
public static int getInt(HttpServletRequest request, String name) {
try {
return Integer.decode(request.getParameter(name));
} catch (Exception e) {
return -1;
}
}

public static long getLong(HttpServletRequest request, String name) {

try {
return Long.valueOf(request.getParameter(name));
} catch (Exception e) {
return -1;
}
}

public static Double getDouble(HttpServletRequest request, String name) {

try {
return Double.valueOf(request.getParameter(name));
} catch (Exception e) {
return -1d;
}
}

public static Boolean getBoolean(HttpServletRequest request, String name) {

try {
return Boolean.valueOf(request.getParameter(name));
} catch (Exception e) {
return false;
}
}

public static String getString(HttpServletRequest request, String name) {
try {
String result = request.getParameter(name);
if (result != null) {
result = result.trim();
}
if ("".equals(result))
result = null;
return result;
} catch (Exception e) {
return null;
}

}
}

Jackson之jackson-databind

https://blog.csdn.net/u011499747/article/details/78762007 CSDN 博客

https://github.com/FasterXML/jackson-databind Github官网API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>

POJO和JSON之间的转化

给出一个足够简单的POJO:

1
2
3
4
public class MyValue {
public String name;
public int age;
}

注意:如果使用getters/setters的话,可以用private/protected修饰属性,这里直接用public修饰了,就不需要getters/setters了。

使用databind,我们需要一个最基础的对象com.fasterxml.jackson.databind.ObjectMapper,这里我们构造一个:

1
ObjectMapper mapper = new ObjectMapper();

注意:这个mapper是可以复用的,就好比HttpClient一样。

简单的把JSON反序列化成Object的用法如下

1
2
3
4
5
6
7
8
9
MyValue value = mapper.readValue(new File("data.json"), MyValue.class);
// or:
value = mapper.readValue(new URL("http://www.dubby.cn/api/entry.json"), MyValue.class);
// or:
value = mapper.readValue("{\"name\":\"Bob\", \"age\":13}", MyValue.class);
-------------------

//将字符串转为实体类
tbShop = mapper.readValue(shopStr, TbShop.class);

简单的把Object序列化成JSON的用法如下:

1
2
3
4
5
mapper.writeValue(new File("result.json"), myResultObject);
// or:
byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject);
// or:
String jsonString = mapper.writeValueAsString(myResultObject);

image-20190303120115098

可以从Jackson-docs存储库中找到更全面的文档; 以及来自该项目的Wiki。但这里有简要的介绍性教程,建议阅读顺序。

1分钟教程:POJO到JSON并返回

最常见的用法是使用JSON,并从中构造一个Plain Old Java Object(“POJO”)。那么让我们从那里开始。简单的2属性POJO像这样:

1
2
3
4
5
6
//注意:也可以使用getter / setter; 这里我们直接使用公共字段:
public class MyValue {
public String name;
公共 INT年龄;
//注意:如果使用getter / setter,可以保留字段`protected`或`private`
}

我们需要一个com.fasterxml.jackson.databind.ObjectMapper用于所有数据绑定的实例,所以让我们构造一个:

1
ObjectMapper mapper =  new  ObjectMapper(); //创建一次,重用

默认实例适合我们使用 - 稍后我们将了解如何在必要时配置映射器实例。用法很简单:

1
2
3
4
5
MyValue值= mapper 。readValue(新 文件(“ data.json ”),myvalue的。类);
//或:
value = mapper 。readValue(新 URL(“ http://some.com/api/entry.json ”),MyValue 。类);
//或:
value = mapper 。readValue(“ { \” name \“:\” Bob \“,\ “年龄\”:13} “, myvalue的。类);

如果我们想写JSON,我们会做相反的事情:

1
2
3
4
5
映射器。writeValue(新 文件(“ result.json ”),myResultObject);
//或:
byte [] jsonBytes = mapper 。writeValueAsBytes(myResultObject);
//或:
String jsonString = mapper 。writeValueAsString(myResultObject);

到现在为止还挺好?

3分钟教程:通用集合,树模型

除了处理简单的Bean风格的POJO之外,您还可以处理JDK ListMaps:

1
2
3
4
5
Map < String,Integer > scoreByName = mapper 。readValue(jsonSource,Map 。类);
List < String > names = mapper 。readValue(jsonSource,列表。类);

//显然可以写出
mapper。writeValue( new File( “ names.json ”),names);

只要JSON结构匹配,类型就很简单。如果您有POJO值,则需要指明实际类型(注意:对于具有Listetc类型的POJO属性,这不是必需的):

1
2
3
Map < String,ResultValue > results = mapper 。readValue(jsonSource,
新 TypeReference < 地图< 字符串,ResultValue > >(){});
//为什么要额外工作?Java Type Erasure否则会阻止类型检测

(注意:无论通用类型如何,序列化都不需要额外的努力)

可是等等!还有更多!

虽然处理Maps,Lists和其他“简单”对象类型(字符串,数字,布尔值)可能很简单,但对象遍历可能很麻烦。这就是Jackson’s Tree模型可以派上用场的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//可以读作通用的JsonNode,如果它可以是Object或Array; 或者,
//如果已知为Object,则为ObjectNode,如果是array,ArrayNode等:
ObjectNode root = mapper。readTree( “ stuff.json ”);
字符串名称 = root。得到( “名字”)。asText();
int age = root。得到( “年龄”)。asInt中();

//也可以修改:这会将子对象添加为属性'other',设置属性'
type'root。与( “其他”)。put( “ type ”, “ student ”);
String json = mapper。writeValueAsString(根);

//与上面一样,我们最终得到像'json'字符串:
// {
// “name”:“Bob”,“age”:13,
// “other”:{
// “type”:“学生“
// }
// }

树模型比数据绑定更方便,特别是在结构高度动态或不能很好地映射到Java类的情况下

SpringMVC 图片上传操作待定

1
2
3
4
5
6
7
8
9
10
11
CommonsMultipartFile shopImg = null;
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
if (commonsMultipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
shopImg = (CommonsMultipartFile) multipartHttpServletRequest.getFile("shopImg");
} else {
modelMap.put("success", false);
modelMap.put("errMsg", "图片上传不能为空");
return modelMap;
}

9 SUIMobile

http://m.sui.taobao.org/

http://m.sui.taobao.org/getting-started/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>我的生活</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<link rel="shortcut icon" href="/favicon.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">

<link rel="stylesheet" href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">
<link rel="stylesheet" href="//g.alicdn.com/msui/sm/0.6.2/css/sm-extend.min.css">

</head>
<body>
<div class="page-group">
<div class="page page-current">
<!-- 你的html代码 -->
</div>
</div>

<script type='text/javascript' src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script>
<script type='text/javascript' src='//g.alicdn.com/msui/sm/0.6.2/js/sm.min.js' charset='utf-8'></script>
<script type='text/javascript' src='//g.alicdn.com/msui/sm/0.6.2/js/sm-extend.min.js' charset='utf-8'></script>

</body>
</html>

店铺注册之JS 实现

image-20190303212002891


image-20190303212023907


image-20190303212045046


image-20190303212140544


image-20190303212159630


1
 

10 店铺类别区域信息的获取

1
2
3
public interface ShopService {
ShopExcution addShop(TbShop tbShop, CommonsMultipartFile ShopImg);
}
1
2
3
4
public interface ShopCategoryService {
//查询TbShopCategory
List<TbShopCategory> findAllByParentIdAndShopCategoryId(TbShopCategory tbShopCategoryCondition);
}
1
2
3
    //查询 TbShopCategory 用mybatispluginshelp2.4开发升级的
//4-8店铺类别区域信息的获取
List<TbShopCategory> findAllByParentIdAndShopCategoryId(@Param("TbShopCategoryCondition") TbShopCategory TbShopCategoryCondition);
1
2
3
4
5
6
7
8
<select id="findAllByParentIdAndShopCategoryId" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from tb_shop_category
where parent_id=#{TbShopCategoryCondition.parent.shopCategoryId}
ORDER BY
priority DESC
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Controller层的实现

private Map<String, Object> getShopInitInfo(Integer id) {
// Map<String, Object> modelMap = new HashMap<String, Object>();
// List<TbShopCategory> shopCategoryList = new ArrayList<TbShopCategory>();
// List<TbArea> areaList = new ArrayList<TbArea>();
// try {
// shopCategoryList = shopCategoryService
// .getShopCategoryList(id);
//// areaList = areaService.getAreaList();
// } catch (Exception e) {
// modelMap.put("success", false);
// modelMap.put("errMsg", e.toString());
// }
// modelMap.put("shopCategoryList", shopCategoryList);
// modelMap.put("areaList", areaList);
// modelMap.put("success", true);
//
// return modelMap;
// }

11 AreaService

1
2
3
4
5
6
public interface AreaService {

@Service
public interface AreaService {
List<TbArea> findAllArea();
}
1
2
3
4
5
6
7
8
9
10
@Service
public class AreaServiceImpl implements AreaService {
@Autowired
private TbAreaMapper tbAreaMapper;

@Override
public List<TbArea> findAllArea() {
return tbAreaMapper.findAll();
}
}

12AreaController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Controller
@RequestMapping("/superadmin")
public class AreaContorller {
@Autowired
private AreaService areaService;
@RequestMapping("/listarea")
public Map<String, Object> listArea() {
Map<String, Object> modelMap = new HashMap<String, Object>();
List<TbArea> allArea = new ArrayList<TbArea>();
try {
allArea = areaService.findAllArea();

modelMap.put("rows", allArea);
modelMap.put("total", allArea.size());
} catch (Exception e) {
modelMap.put("success", false);
modelMap.put("errMsg", e.toString());
}
return modelMap;
}
}

#13使用 SpringBoot + kaptcha 生成、校对 验证码

https://blog.csdn.net/larger5/article/details/79522105

https://www.jianshu.com/p/1f2f7c47e812

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
2、pom
(SpringBoot+thymeleaf+web+kaptcha )
注意引入 kaptcha 的 Maven 依赖

<!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>

3、KaptchaConfig
即 kaptcha 的配置文件

package com.cun.conf;

import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;

@Component
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha();
Properties properties = new Properties();
// 图片边框
properties.setProperty("kaptcha.border", "yes");
// 边框颜色
properties.setProperty("kaptcha.border.color", "105,179,90");
// 字体颜色
properties.setProperty("kaptcha.textproducer.font.color", "red");
// 图片宽
properties.setProperty("kaptcha.image.width", "110");
// 图片高
properties.setProperty("kaptcha.image.height", "40");
// 字体大小
properties.setProperty("kaptcha.textproducer.font.size", "30");
// session key
properties.setProperty("kaptcha.session.key", "code");
// 验证码长度
properties.setProperty("kaptcha.textproducer.char.length", "4");
// 字体
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);

return defaultKaptcha;
}
}

4、KaptchaController
验证码控制层

package com.cun.controller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.google.code.kaptcha.impl.DefaultKaptcha;

@Controller
public class KaptchaController {

/**
* 1、验证码工具
*/
@Autowired
DefaultKaptcha defaultKaptcha;

/**
* 2、生成验证码
* @param httpServletRequest
* @param httpServletResponse
* @throws Exception
*/
@RequestMapping("/defaultKaptcha")
public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws Exception {
byte[] captchaChallengeAsJpeg = null;
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// 生产验证码字符串并保存到session中
String createText = defaultKaptcha.createText();
httpServletRequest.getSession().setAttribute("rightCode", createText);
// 使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
BufferedImage challenge = defaultKaptcha.createImage(createText);
ImageIO.write(challenge, "jpg", jpegOutputStream);
} catch (IllegalArgumentException e) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}

// 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
}

/**
* 3、校对验证码
* @param httpServletRequest
* @param httpServletResponse
* @return
*/
@RequestMapping("/imgvrifyControllerDefaultKaptcha")
public ModelAndView imgvrifyControllerDefaultKaptcha(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
ModelAndView andView = new ModelAndView();
String rightCode = (String) httpServletRequest.getSession().getAttribute("rightCode");
String tryCode = httpServletRequest.getParameter("tryCode");
System.out.println("rightCode:"+rightCode+" ———— tryCode:"+tryCode);
if (!rightCode.equals(tryCode)) {
andView.addObject("info", "错误的验证码");
andView.setViewName("index");
} else {
andView.addObject("info", "登录成功");
andView.setViewName("success");
}
return andView;
}

@RequestMapping("/toIndex")
public String toIndex() {
return "index";
}
}


5、application.yml SpringBoot 核心配置文件
server:
port: 80
context-path: /

6、主界面 index.html
<!DOCTYPE html>
<!-- thymeleaf 提示功能 -->
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8"></meta>
<title>hello</title>
<!-- 引入BootStrap -->
<link rel="stylesheet" href="../bootstrap3/css/bootstrap-theme.min.css" />
<link rel="stylesheet" href="../bootstrap3/css/bootstrap.min.css" />
<script type="text/javascript" src="../bootstrap3/js/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="../bootstrap3/js/bootstrap.min.js"></script>
</head>
<style type="text/css">
body {
padding: 10px
}
</style>
<body>
<!-- 提示 -->
<h3 th:text="${info}"></h3>
<div>
<!-- 后面添加参数起到清除缓存作用 -->
<img alt="验证码" onclick="this.src='/defaultKaptcha?d='+new Date()*1" src="/defaultKaptcha" />
</div>
<form action="imgvrifyControllerDefaultKaptcha" >
<input type="text" name="tryCode" />
<input type="submit" value="提交" class="btn btn-success"></input>
</form>
</body>
</html>




7、验证成功界面 success.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"></meta>
<title>验证成功</title>
</head>
<body>
<h1>验证成功</h1>
</body>
</html>
https://www.jianshu.com/p/1f2f7c47e812

14 SpringBoot 整合日志文件

https://www.cnblogs.com/zhangjianbing/p/8992897.html

https://blog.csdn.net/ws_kfxd/article/details/8466559

1 依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.10.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>

店铺信息编辑值dao开发